<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as THREE from 'three'
import TWEEN from '@tweenjs/tween.js'

const container = ref(null)
const score = ref(0)
const gameOver = ref(false)
const bestScore = ref(parseInt(localStorage.getItem('jumpGameBestScore')) || 0)

// 游戏状态
const gameState = ref({
  isPressed: false,
  pressTime: 0,
  jumperStatus: 0, // 0: 静止, 1: 跳跃中
})

let scene, camera, renderer, jumper, cubes, cubeMaterial

// 游戏配置
const config = {
  // 跳跃者
  jumperSize: { width: 1, height: 2, depth: 1 },
  jumperColor: 0x232323,
  jumperSpeed: 0.2,
  
  // 方块
  cubeSize: { width: 4, height: 2, depth: 4 },
  cubeColors: [0x67C23A, 0x409EFF, 0xE6A23C, 0xF56C6C],
  cubeMinDistance: 2.5,
  cubeMaxDistance: 4.5,
  
  // 相机
  cameraY: 10,
  cameraZ: 10,
}

// 初始化场景
const initScene = () => {
  scene = new THREE.Scene()
  
  // 相机
  camera = new THREE.OrthographicCamera(
    window.innerWidth / -50,
    window.innerWidth / 50,
    window.innerHeight / 50,
    window.innerHeight / -50,
    0.1,
    1000
  )
  
  // 渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setClearColor(0xd3d3d3, 1)
  container.value.appendChild(renderer.domElement)
  
  // 光源
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
  directionalLight.position.set(100, 100, 100)
  scene.add(directionalLight)
  
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.3)
  scene.add(ambientLight)
  
  // 初始化材质
  cubeMaterial = new THREE.MeshLambertMaterial({ color: config.cubeColors[0] })
  
  // 初始化跳跃者
  initJumper()
  
  // 初始化方块
  cubes = []
  createCube()
  createCube()
  
  // 调整相机位置
  updateCameraPosition()
  
  // 开始渲染
  animate()
}

// 初始化跳跃者
const initJumper = () => {
  const geometry = new THREE.BoxGeometry(
    config.jumperSize.width,
    config.jumperSize.height,
    config.jumperSize.depth
  )
  const material = new THREE.MeshLambertMaterial({ color: config.jumperColor })
  jumper = new THREE.Mesh(geometry, material)
  jumper.position.y = config.jumperSize.height / 2
  scene.add(jumper)
}

// 创建方块
const createCube = () => {
  const geometry = new THREE.BoxGeometry(
    config.cubeSize.width,
    config.cubeSize.height,
    config.cubeSize.depth
  )
  const material = new THREE.MeshLambertMaterial({
    color: config.cubeColors[Math.floor(Math.random() * config.cubeColors.length)]
  })
  const cube = new THREE.Mesh(geometry, material)
  
  if (cubes.length) {
    const lastCube = cubes[cubes.length - 1]
    const distance = config.cubeMinDistance +
      Math.random() * (config.cubeMaxDistance - config.cubeMinDistance)
    
    // 随机在x轴或z轴方向放置
    if (Math.random() > 0.5) {
      cube.position.x = lastCube.position.x + distance
      cube.position.z = lastCube.position.z
    } else {
      cube.position.z = lastCube.position.z + distance
      cube.position.x = lastCube.position.x
    }
  }
  
  cube.position.y = config.cubeSize.height / 2
  cubes.push(cube)
  scene.add(cube)
}

// 更新相机位置
const updateCameraPosition = () => {
  camera.position.x = jumper.position.x
  camera.position.z = jumper.position.z + config.cameraZ
  camera.position.y = config.cameraY
  camera.lookAt(jumper.position)
}

// 处理跳跃
const handleJump = () => {
  if (gameState.value.jumperStatus === 0) {
    gameState.value.jumperStatus = 1
    const distance = gameState.value.pressTime * config.jumperSpeed
    const targetX = jumper.position.x
    const targetZ = jumper.position.z
    
    // 根据按压时间计算跳跃距离
    if (distance < config.cubeMinDistance) {
      gameOver.value = true
      return
    }
    
    // 动画跳跃
    let jumpTween = new TWEEN.Tween(jumper.position)
      .to({
        x: targetX + distance,
        y: config.jumperSize.height / 2 + 4,
        z: targetZ
      }, 200)
      .easing(TWEEN.Easing.Quadratic.Out)
      .start()
    
    // 下落
    jumpTween.onComplete(() => {
      new TWEEN.Tween(jumper.position)
        .to({
          y: config.jumperSize.height / 2
        }, 200)
        .easing(TWEEN.Easing.Quadratic.In)
        .start()
        .onComplete(() => {
          checkLanding()
        })
    })
  }
}

// 检查着陆
const checkLanding = () => {
  const position = jumper.position.clone()
  
  // 检查是否落在方块上
  let landed = false
  cubes.forEach(cube => {
    const distance = position.distanceTo(cube.position)
    if (distance < config.cubeSize.width / 2) {
      landed = true
      score.value++
      if (score.value > bestScore.value) {
        bestScore.value = score.value
        localStorage.setItem('jumpGameBestScore', bestScore.value)
      }
      createCube()
      if (cubes.length > 3) {
        scene.remove(cubes[0])
        cubes.shift()
      }
    }
  })
  
  if (!landed) {
    gameOver.value = true
  }
  
  gameState.value.jumperStatus = 0
}

// 动画循环
const animate = () => {
  if (!gameOver.value) {
    requestAnimationFrame(animate)
    TWEEN.update()
    updateCameraPosition()
    renderer.render(scene, camera)
  }
}

// 事件处理
const handleMouseDown = () => {
  if (!gameOver.value) {
    gameState.value.isPressed = true
    gameState.value.pressTime = 0
  }
}

const handleMouseUp = () => {
  if (!gameOver.value && gameState.value.isPressed) {
    gameState.value.isPressed = false
    handleJump()
  }
}

// 重新开始游戏
const restartGame = () => {
  score.value = 0
  gameOver.value = false
  
  // 重置场景
  scene.remove.apply(scene, scene.children)
  cubes = []
  
  initJumper()
  createCube()
  createCube()
  
  updateCameraPosition()
  animate()
}

// 组件挂载
onMounted(() => {
  initScene()
  
  window.addEventListener('mousedown', handleMouseDown)
  window.addEventListener('mouseup', handleMouseUp)
  window.addEventListener('touchstart', handleMouseDown)
  window.addEventListener('touchend', handleMouseUp)
  
  // 蓄力动画
  setInterval(() => {
    if (gameState.value.isPressed) {
      gameState.value.pressTime += 0.1
    }
  }, 100)
})

// 组件卸载
onUnmounted(() => {
  window.removeEventListener('mousedown', handleMouseDown)
  window.removeEventListener('mouseup', handleMouseUp)
  window.removeEventListener('touchstart', handleMouseDown)
  window.removeEventListener('touchend', handleMouseUp)
})
</script>

<template>
  <div class="jump-game">
    <div ref="container" class="game-container"></div>
    
    <!-- 游戏界面 -->
    <div class="game-ui">
      <div class="score">得分: {{ score }}</div>
      <div class="best-score">最高分: {{ bestScore }}</div>
      
      <!-- 蓄力条 -->
      <div 
        v-if="gameState.isPressed" 
        class="power-bar"
      >
        <div 
          class="power-fill"
          :style="{ width: `${Math.min(gameState.pressTime * 20, 100)}%` }"
        ></div>
      </div>
      
      <!-- 游戏结束界面 -->
      <div v-if="gameOver" class="game-over">
        <h2>游戏结束</h2>
        <p>得分: {{ score }}</p>
        <p>最高分: {{ bestScore }}</p>
        <button @click="restartGame">重新开始</button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.jump-game {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.game-container {
  width: 100%;
  height: 100%;
}

.game-ui {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  pointer-events: none;
}

.score,
.best-score {
  position: absolute;
  top: 20px;
  font-size: 24px;
  color: #333;
  padding: 10px;
  background: rgba(255, 255, 255, 0.8);
  border-radius: 4px;
}

.score {
  left: 20px;
}

.best-score {
  right: 20px;
}

.power-bar {
  position: absolute;
  bottom: 50px;
  left: 50%;
  transform: translateX(-50%);
  width: 200px;
  height: 10px;
  background: rgba(255, 255, 255, 0.5);
  border-radius: 5px;
  overflow: hidden;
}

.power-fill {
  height: 100%;
  background: #409EFF;
  transition: width 0.1s linear;
}

.game-over {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(255, 255, 255, 0.9);
  padding: 20px 40px;
  border-radius: 8px;
  text-align: center;
  pointer-events: auto;
}

.game-over h2 {
  margin-bottom: 20px;
  color: #333;
}

.game-over p {
  margin: 10px 0;
  color: #666;
}

.game-over button {
  margin-top: 20px;
  padding: 10px 20px;
  background: #409EFF;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.2s;
}

.game-over button:hover {
  background: #66b1ff;
}
</style> 